
Imports System.Text
Imports System.Collections

Namespace std
    Public Class vector(Of valueType)
#If RETIRED Then
        Inherits IComparable2(Of vector(Of valueType))
#End If
        Implements backoperatingContainer(Of valueType), IComparable(Of vector(Of valueType)), IComparable

        Private Shared ALLOCATE_ALERT As Boolean = False

        Public Const defaultInitialSize As Int64 = 4
        Protected _data() As valueType
        Protected _size As Int64

        Public Class iterator
            Inherits randomAccessIterator(Of valueType)

            Private owner As vector(Of valueType) = Nothing
            Private index As Int64 = 0

            Public Sub New(ByVal owner As vector(Of valueType), ByVal index As Int64)
                Me.owner = owner
                Me.index = index
            End Sub

            Protected Overrides Function traversal(ByVal prev As Boolean) As Boolean
                assert(Not owner Is Nothing, "do not have owner, cannot traversal.")
                If prev Then
                    index -= 1
                Else
                    index += 1
                End If
                If owner.availableIndex(index) Then
                    p = owner(index)
                    Return True
                Else
                    p = Nothing
                    Return False
                End If
            End Function
        End Class

        Protected Function full() As Boolean
            debugassert(size() <= capacity(), "size() > capacity() in vector")
            Return size() = capacity()
        End Function

        Public Property capacity() As Int64
            Get
                If _data Is Nothing Then
                    Return 0
                Else
                    Return _data.Length()
                End If
            End Get
            Set(ByVal value As Int64)
                If _data Is Nothing Then
                    If value > 0 Then
                        If ALLOCATE_ALERT Then
                            perfCheckPoint("allocate memory" _
                                           , "capacity redim _data(value-1) from 0 to " + Convert.ToString(value))
                        End If
                        ReDim _data(value - 1)
                    End If
                    'value = 0 andalso _data is nothing, so do not need to do anything here
                ElseIf value <> _data.Length() Then
                    If value > 0 Then
                        If ALLOCATE_ALERT Then
                            perfCheckPoint("allocate memory" _
                                           , "capacity redim preserve _data(value-1) from " _
                                           + Convert.ToString(_data.Length()) + " to " + Convert.ToString(value))
                        End If
                        ReDim Preserve _data(value - 1)
                    Else
                        If ALLOCATE_ALERT Then
                            perfCheckPoint("allocate memory" _
                                           , "capacity redim _data(value-1) from " _
                                           + Convert.ToString(_data.Length()) + " to " + Convert.ToString(value))
                        End If
                        ReDim _data(-1)
                    End If
                End If
                'value = _data.length, also do not need to do anything here
            End Set
        End Property

        Public Function size2() As Int64 Implements backoperatingContainer(Of valueType).size
            Return size()
        End Function

        Public Property size() As Int64
            Get
                Return _size
            End Get
            Set(ByVal value As Int64)
                If value > capacity() Then
                    If ALLOCATE_ALERT Then
                        perfCheckPoint("allocate memory", "size capacity()=(value<<1)")
                    End If
                    capacity() = (value << 1)
                ElseIf value < (capacity() >> 2) AndAlso value > defaultInitialSize AndAlso value < _size Then
                    'only reduce capacity when empty block over 75% and value larger than 4
                    'and value < current used block count, so will not reduce size when push_back
                    If ALLOCATE_ALERT Then
                        perfCheckPoint("allocate memory", "size capacity()>>=1")
                    End If
                    capacity() >>= 1
                End If
                If _size > value Then
                    memclr(_data, value, min(capacity(), _size) - value)
                End If
                _size = value
            End Set
        End Property

        Public Function availableIndex(ByVal index As Int64) As Boolean
            If index >= 0 And index < size() Then
                Return True
            Else
                Return False
            End If
        End Function

        Public Function data() As valueType()
            reserve()
            Return _data
        End Function

        'sometimes, do not need to reverse the data serial, such as for sorting
        Public Function rawdata() As valueType()
            Return _data
        End Function

        Public Shared Operator +(ByVal this As vector(Of valueType)) As valueType()
            If Not this Is Nothing Then
                Return this.data()
            Else
                Return Nothing
            End If
        End Operator

        Public Function take(ByVal index As Int64, ByRef value As valueType) As Boolean
            If availableIndex(index) Then
                value = _data(index)
                Return True
            Else
                value = Nothing
                Return False
            End If
        End Function

        Default Public Property at(ByVal index As Int64) As valueType Implements backoperatingContainer(Of valueType).at
            Get
                Dim rtn As valueType
                take(index, rtn)
                Return rtn
            End Get
            Set(ByVal value As valueType)
                [set](index, value)
            End Set
        End Property

        Public Function push_back(ByVal vs() As valueType, Optional ByVal start As Int64 = 0 _
                                , Optional ByVal nsize As Int64 = npos) As Boolean
            If Not vs Is Nothing Then
                If nsize = npos Then
                    nsize = vs.Length - start
                End If

                If nsize > 0 AndAlso nsize + start <= vs.Length() Then
                    If capacity() < size() + nsize Then
                        'there are two solutions, i cannot confirm the perf for each now
                        'first,
                        'capacity() += (nsize << 1)
                        'second,
                        capacity() += ((size() + nsize) << 1)
                    End If
                    Dim i As Int64
                    For i = 0 To nsize - 1
                        copy(_data(size() + i), vs(start + i))
                    Next
                    size() += nsize

                    Return True
                Else
                    Return False
                End If
            Else
                Return False
            End If
        End Function

        Public Function push_back(ByVal vs As vector(Of valueType)) As Boolean
            If Not vs Is Nothing Then
                Return push_back(vs.data)
            Else
                Return False
            End If
        End Function

        Public Function push_back(ByVal value As valueType) As Boolean _
                                 Implements backoperatingContainer(Of valueType).push_back
            If full() Then
                If capacity() = 0 Then
                    'for cases with initialsize set to 0
                    capacity() = defaultInitialSize
                Else
                    capacity() <<= 1
                End If
            End If
            copy(_data(size()), value)
            size() += 1

            Return True
        End Function

        Public Function find(ByVal k As valueType) As Int64
            Dim i As Int32
            For i = 0 To size() - 1
                If compare(k, _data(i)) = 0 Then
                    Exit For
                End If
            Next

            If i = size() Then
                i = npos
            Else
                debugassert(i < size(), "caught i > size()")
            End If

            Return i
        End Function

        Public Sub fill(ByRef dest() As valueType)
            Dim i As Int64
            If dest Is Nothing OrElse dest.Length() <> size() Then
                ReDim dest(size() - 1)
            End If
            For i = 0 To size() - 1
                copy(dest(i), _data(i))
            Next
        End Sub

        Public Function empty() As Boolean Implements backoperatingContainer(Of valueType).empty
            Return size() = 0
        End Function

        Public Function pop_back() As Boolean Implements backoperatingContainer(Of valueType).pop_back
            If Not empty() Then
                size() -= 1
                Return True
            Else
                Return False
            End If
        End Function

        Public Property front() As valueType
            Get
                If Not empty() Then
                    Return _data(0)
                Else
                    Return Nothing
                End If
            End Get
            Set(ByVal value As valueType)
                If Not empty() Then
                    copy(_data(0), value)
                End If
            End Set
        End Property

        Public Property back() As valueType Implements backoperatingContainer(Of valueType).back
            Get
                If Not empty() Then
                    Return _data(size() - 1)
                Else
                    Return Nothing
                End If
            End Get
            Set(ByVal value As valueType)
                If Not empty() Then
                    copy(_data(size() - 1), value)
                End If
            End Set
        End Property

        'this is the only iterator follows all rules in stl, end() can be -1 to the last one,
        'and rend can be +1 to the first one
        Public Function begin() As iterator
            Return New iterator(Me, 0)
        End Function

        Public Function container_iterator_begin() As container(Of valueType).iterator _
            Implements container(Of valueType).begin
            Return begin()
        End Function

        Public Function [end]() As iterator
            Return New iterator(Me, size())
        End Function

        Public Function container_iterator_end() As container(Of valueType).iterator _
            Implements container(Of valueType).end
            Return [end]()
        End Function

        Public Function rbegin() As iterator
            Return New iterator(Me, size() - 1)
        End Function

        Public Function container_iterator_rbegin() As container(Of valueType).iterator _
            Implements container(Of valueType).rbegin
            Return rbegin()
        End Function

        Public Function rend() As iterator
            Return New iterator(Me, -1)
        End Function

        Public Function container_iterator_rend() As container(Of valueType).iterator _
            Implements container(Of valueType).rend
            Return rend()
        End Function

        Public Function insert(ByVal value As valueType) As container(Of valueType).iterator _
                                                                Implements backoperatingContainer(Of valueType).insert
            push_back(value)
            Return rbegin()
        End Function

        Private Sub clear(ByVal newsize As Int64)
            If newsize < 0 OrElse newsize >= maxInt32 Then
                newsize = defaultInitialSize
                raiseError(errorHandle.errorType.exclamation, "newsize is not in the range of [0, maxint32).")
            End If
            size() = 0
            capacity() = newsize
        End Sub

        Public Sub clear() Implements backoperatingContainer(Of valueType).clear
            clear(defaultInitialSize)
        End Sub

        Public Function [erase](ByVal start As Int64, ByVal [end] As Int64) As Boolean
            If start = [end] Then
                Return True
            End If
            If start > [end] Then
                swap(start, [end])
            End If
            If start < 0 Then
                start = 0
            End If

            If availableIndex(start) Then
                If [end] >= size() Then
                    size() = start
                Else
                    memmove(_data, start, _data, [end], size() - [end])
                    size() -= [end] - start
                End If

                Return True
            Else
                Return False
            End If
        End Function

        Public Function [erase](ByVal index As Int64) As Boolean
            Return [erase](index, index + 1)
        End Function

        Public Function [erase](ByVal i As valueType) As Boolean
            Return [erase](find(i))
        End Function

        Public Function [set](ByVal index As Int64, ByVal value As valueType) As Boolean
            If availableIndex(index) Then
                copy(_data(index), value)
                Return True
            Else
                Return False
            End If
        End Function

        Public Sub New()
            clear(defaultInitialSize)
        End Sub

        Public Sub New(ByVal initialSize As Int64)
            clear(initialSize)
        End Sub

        Public Sub reserve()
            capacity() = size()
        End Sub

        Public Sub freeMemory()
            reserve()
        End Sub

        Public Overridable Function clone() As Object Implements System.ICloneable.Clone
            Dim rtn As vector(Of valueType) = Nothing

            'allocate memory one time only
            rtn = alloc(Me)
            rtn.push_back(_data, 0, size())
#If RETIRED Then
            rtn.size() = size()
#End If

            Return rtn
        End Function

        Public Delegate Function ToStringMethod(ByVal v As valueType) As String

        Protected Function emptyToString(ByVal v As valueType) As String
            Return Convert.ToString(v)
        End Function

        Public Overloads Function ToString(ByVal startIndex As Int64, ByVal f As ToStringMethod, _
                                           Optional ByVal seperator As String = character.tab) As String
            assert(Not f Is Nothing, "f is not a valid ToStringMethod.")
            Dim i As Int64
            Dim rtn As StringBuilder = Nothing
            rtn = New StringBuilder()
            For i = startIndex To size() - 1
                rtn.Append(f(Me(i)))
                If i < size() - 1 Then
                    rtn.Append(seperator)
                End If
            Next

            Return Convert.ToString(rtn)
        End Function

        Public Overloads Function ToString(ByVal f As ToStringMethod, _
                                            Optional ByVal seperator As String = character.tab) As String
            Return ToString(0, f, seperator)
        End Function

        Public Overloads Function ToString(ByVal seperator As String) As String
            Return ToString(AddressOf emptyToString, seperator)
        End Function

        Public Overloads Function ToString(ByVal startIndex As Int64, _
                                           Optional ByVal seperator As String = character.tab) As String
            Return ToString(startIndex, AddressOf emptyToString, seperator)
        End Function

        Public Overrides Function ToString() As String
            Return ToString(character.tab)
        End Function

        Public Shared Widening Operator CType(ByVal this As vector(Of valueType)) As valueType()
            Dim rtn() As valueType = Nothing
            this.fill(rtn)
            Return rtn
        End Operator

        Public Shared Widening Operator CType(ByVal this() As valueType) As vector(Of valueType)
            Dim rtn As vector(Of valueType) = Nothing
            rtn = New vector(Of valueType)()
            If Not this Is Nothing AndAlso Not rtn.push_back(this) Then
                raiseError("cannot insert all elements in valueType array, memory limited?" _
                           , errorHandle.errorType.system)
            End If

            Return rtn
        End Operator

        Public Shared Function modget(ByVal t As vector(Of valueType), ByVal i As Int64) As valueType
            If t Is Nothing Then
                Return Nothing
            Else
                Return t.modget(i)
            End If
        End Function

        Public Function modget(ByVal i As Int64) As valueType
            If i >= size() Then
                Return at(i Mod size())
            Else
                Return at(i)
            End If
        End Function

#If RETIRED Then
        Public Shared Operator <>(ByVal this As vector(Of valueType), ByVal that As vector(Of valueType)) As Boolean
            Return Not this = that
        End Operator

        Public Shared Operator =(ByVal this As vector(Of valueType), ByVal that As vector(Of valueType)) As Boolean
            If this Is Nothing AndAlso that Is Nothing Then
                Return True
            ElseIf this Is Nothing OrElse that Is Nothing Then
                Return False
            Else
                Return compare(this, that) = 0
            End If
        End Operator
#End If

        Public Function CompareTo(ByVal that As vector(Of valueType)) As Int32 _
                                                            Implements IComparable(Of vector(Of valueType)).CompareTo
            If size() <> that.size() Then
                Return size() - that.size()
            Else
#If Not (PocketPC OrElse Smartphone) Then
                Return memcmp(_data, that._data, size())
#Else
                Return -1
#End If
            End If
        End Function

        Public Function CompareTo(ByVal that As Object) As Int32 Implements IComparable.CompareTo
            Return CompareTo(convertor.cast(Of vector(Of valueType))(that, False))
        End Function

        Public Shared Operator =(ByVal this As vector(Of valueType), ByVal that As vector(Of valueType)) As Boolean
            Return operatorEqual(this, that)
        End Operator

        Public Shared Operator <>(ByVal this As vector(Of valueType), ByVal that As vector(Of valueType)) As Boolean
            Return operatorUnequal(this, that)
        End Operator

        Public Shared Operator =(ByVal this As vector(Of valueType), ByVal that As Object) As Boolean
            Return operatorEqual(this, that)
        End Operator

        Public Shared Operator <>(ByVal this As vector(Of valueType), ByVal that As Object) As Boolean
            Return operatorUnequal(this, that)
        End Operator

        Private Class testActions
            Protected Shared Sub parseArgument(ByVal obj As Object, ByRef v As vector(Of String))
                v = convertor.cast(Of vector(Of String))(obj)
                assert(Not v Is Nothing, "v is nothing.")
            End Sub

            Protected Shared Sub rndarray(ByRef a As memblock(Of String))
                If a Is Nothing Then
                    a = New memblock(Of String)()
                Else
                    a.clear()
                End If
                a.size() = rnd(0, 1024, True)

                Dim i As Int64
                For i = 0 To a.size() - 1
                    a(i) = createGUID()
                Next
            End Sub
        End Class

        Private Class unittestActions
            Inherits testActions

            Public Shared Sub size(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                Dim oldsize As Int64
                oldsize = v.size()

                Dim i As Int64
                Dim till As Int64
                till = rnd(0, 1024, True)
                raiseError("push_back to make size() += " + Convert.ToString(till))
                For i = 0 To till - 1
                    v.push_back(createGUID())
                Next

                assert(v.size() - oldsize = till _
                       , "cannot update size property after " + Convert.ToString(till) + " push_back operations.")
            End Sub

            Public Shared Sub clear(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("clear()")
                v.clear()

                assert(v.size() = 0, "v.size() <> 0 after clear.")
                Dim i As Int64
                For i = 0 To v.capacity() - 1
                    assert(v(i) Is Nothing, "cannot clear " + Convert.ToString(i) + " after clear operation.")
                Next
            End Sub

            Public Shared Sub data(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                Dim a As memblock(Of String) = Nothing
                rndarray(a)

                Dim oldsize As Int64
                oldsize = v.size()
                raiseError("data() to make a reverse operation.")
                v.push_back(+a)

#If Not (PocketPC OrElse Smartphone) Then
                assert(memcmp(v.data, oldsize, +a, 0, a.size()) = 0, "caught v.data <> a.data.")
#End If
            End Sub

            Public Shared Sub push_back(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                Dim s As String = Nothing
                s = createGUID()

                Dim oldsize As Int64
                oldsize = v.size()
                raiseError("push_back to make size() += 1")
                v.push_back(s)

                assert(v.size() - oldsize = 1, "v.size() - oldsize <> 1 after one push_back operation.")
                assert(strsame(v.back(), s, True), "v.back() <> s.")
            End Sub

            Public Shared Sub find(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                Dim a As memblock(Of String) = Nothing
                rndarray(a)

                Dim oldsize As Int64
                oldsize = v.size()
                v.push_back(+a)

                raiseError("find(const string&).")
                Dim i As Int64
                For i = 0 To a.size() - 1
                    assert(v.find(a(i)) = oldsize + i _
                           , "caught a(" + Convert.ToString(i) + ") is not at the place expected.")
                Next
            End Sub

            Public Shared Sub fill(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                'confirm there is at lease one element in vector
                v.push_back(createGUID())

                Dim a() As String = Nothing
                raiseError("fill(string[])")
                v.fill(a)

                assert(Not a Is Nothing AndAlso a.Length() = v.size(), "found a is nothing or a.length()<>v.size().")
                'avoid reallocate memory message
#If Not (PocketPC OrElse Smartphone) Then
                assert(memcmp(v._data, 0, a, 0, a.Length()) = 0, "found v is not same as a.")
#End If
            End Sub

            Public Shared Sub empty(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("empty test with a clear.")
                v.clear()
                assert(v.empty(), "v is not empty after clear.")
            End Sub

            Public Shared Sub front(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("front(), clear then push_back.")
                v.clear()
                Dim s As String = Nothing
                s = createGUID()
                v.push_back(s)
                assert(strsame(v.front(), s, True), "v.front <> s.")
            End Sub

            Public Shared Sub back(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                Dim s As String = Nothing
                s = createGUID()
                raiseError("back(), push_back.")
                v.push_back(s)
                assert(strsame(v.back(), s, True), "v.back <> s.")
            End Sub

            Public Shared Sub [erase](ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                Dim a As memblock(Of String) = Nothing

                Dim i As Int64
                Dim j As Int64
                i = rnd(0, v.size(), True)
                j = rnd(0, v.size(), True)
                If i > j Then
                    swap(i, j)
                End If

                Dim k As Int64
                For k = i To j - 1
                    a += v(k)
                Next

                raiseError("erase from " + Convert.ToString(i) + " to " + Convert.ToString(j))
                If rnd(0, 2, True) = 0 Then
                    assert(v.erase(i, j) _
                           , "v.erase(" + Convert.ToString(i) + "," + Convert.ToString(j) + ") returns false.")
                Else
                    assert(v.erase(j, i) _
                           , "v.erase(" + Convert.ToString(j) + "," + Convert.ToString(i) + ") returns false.")
                End If

                'confirm at least one element here.
                raiseError("push_back to make at least one element, then erase a random element.")
                v.push_back(createGUID())
                i = rnd(0, v.size(), True)
                a += v(i)
                assert(v.erase(i), "v.erase(" + Convert.ToString(i) + ") returns false.")

                'confirm at least one element here.
                raiseError("push_back to make at least one element, then erase a random element with const string&.")
                v.push_back(createGUID())
                i = rnd(0, v.size(), True)
                a += v(i)
                assert(v.erase(v(i)), "v.erase(v(" + Convert.ToString(i) + ")) returns false.")

                For i = 0 To a.size() - 1
                    assert(v.find(a(i)) = npos, "still find " + a(i) + " in vector.")
                Next
            End Sub

            Public Shared Sub reverse(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                Dim a() As String = Nothing
                raiseError("reverse, data() then reverse.")
                a = v.data()
                v.reserve()

                assert(v.capacity() = v.size(), "v.capacity() <> v.size() after reverse.")
#If Not (PocketPC OrElse Smartphone) Then
                assert(memcmp(v.data, 0, a, 0, a.Length) = 0, "v.data <> a after reverse.")
#End If
            End Sub

            Public Shared Sub clone(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                Dim v2 As vector(Of String) = Nothing
                raiseError("clone to a new instance.")
                copy(v2, v)

                assert(compare(v, v2) = 0, "v<>v2")
            End Sub
        End Class

        Public Shared Sub automaticUnittest()
            Dim roundcount As Int64 = 1024
            If isreleasebuild() Then
                roundcount *= 20
            End If
            ALLOCATE_ALERT = True

            raiseError("******** automatical vector unitTest ********", errorHandle.errorType.application)

            Dim v As vector(Of String) = Nothing
            v = New vector(Of String)()

            randomrun.invoke(roundcount, v _
                             , New randomrun.info(0.12, AddressOf unittestActions.size) _
                             , New randomrun.info(0.04, AddressOf unittestActions.clear) _
                             , New randomrun.info(0.1, AddressOf unittestActions.data) _
                             , New randomrun.info(0.12, AddressOf unittestActions.push_back) _
                             , New randomrun.info(0.02, AddressOf unittestActions.find) _
                             , New randomrun.info(0.1, AddressOf unittestActions.fill) _
                             , New randomrun.info(0.04, AddressOf unittestActions.empty) _
                             , New randomrun.info(0.04, AddressOf unittestActions.front) _
                             , New randomrun.info(0.1, AddressOf unittestActions.back) _
                             , New randomrun.info(0.1, AddressOf unittestActions.erase) _
                             , New randomrun.info(0.1, AddressOf unittestActions.reverse) _
                             , New randomrun.info(0.02, AddressOf unittestActions.clone))

            raiseError("******** finish automatical unitTest ********", errorHandle.errorType.application)
        End Sub

        Private Class perftestActions
            Inherits testActions

            Public Shared Sub size(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("size = " + Convert.ToString(v.size()))
            End Sub

            Public Shared Sub clear(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("clear()")
                v.clear()
            End Sub

            Public Shared Sub data(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("data()")
                v.data()
            End Sub

            Public Shared Sub push_back(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("push_back()")
                v.push_back(createGUID())
            End Sub

            Public Shared Sub find(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("find()")
                v.find(createGUID())
            End Sub

            Public Shared Sub fill(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("fill()")
                v.fill(Nothing)
            End Sub

            Public Shared Sub empty(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("empty() = " + Convert.ToString(v.empty()))
            End Sub

            Public Shared Sub front(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("front() = " + v.front())
            End Sub

            Public Shared Sub back(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("back() = " + v.back())
            End Sub

            Public Shared Sub [erase](ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("erase()")
                If Not v.empty() Then
                    v.erase(Convert.ToInt64(rnd(0, v.size(), True)))
                End If
            End Sub

            Public Shared Sub reserve(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("reserve()")
                v.reserve()
            End Sub

            Public Shared Sub clone(ByVal obj As Object)
                Dim v As vector(Of String) = Nothing
                parseArgument(obj, v)

                raiseError("clone()")
                Dim v2 As vector(Of String) = Nothing
                copy(v2, v)
            End Sub
        End Class

        Public Shared Sub performanceTest()
            Dim roundcount As Int64 = 102400
            If isreleasebuild() Then
                roundcount *= 20
            End If
            ALLOCATE_ALERT = True

            raiseError("******** automatical vector perfTest ********", errorHandle.errorType.application)

            Dim v As vector(Of String) = Nothing
            v = New vector(Of String)()

            randomrun.invoke(roundcount, v _
                             , New randomrun.info(0.08, AddressOf perftestActions.size) _
                             , New randomrun.info(0.04, AddressOf perftestActions.clear) _
                             , New randomrun.info(0.1, AddressOf perftestActions.data) _
                             , New randomrun.info(0.35, AddressOf perftestActions.push_back) _
                             , New randomrun.info(0.02, AddressOf perftestActions.find) _
                             , New randomrun.info(0.1, AddressOf perftestActions.fill) _
                             , New randomrun.info(0.02, AddressOf perftestActions.empty) _
                             , New randomrun.info(0.02, AddressOf perftestActions.front) _
                             , New randomrun.info(0.05, AddressOf perftestActions.back) _
                             , New randomrun.info(0.05, AddressOf perftestActions.erase) _
                             , New randomrun.info(0.05, AddressOf perftestActions.reserve) _
                             , New randomrun.info(0.02, AddressOf perftestActions.clone))

            raiseError("******** finish automatical perfTest ********", errorHandle.errorType.application)
        End Sub
    End Class

    Public Class vectorStringComparer
        Implements IComparer

        Public Const typeSupport As String = "nsu"

        Private Class sortMethodDefine
            Public Const number As Char = character.n
            Public Const [string] As Char = character.s
            Public Const utf8 As Char = character.u
        End Class

        Private Class factorDefine
            Implements ICloneable

            Public columnIndex As Int64
            Public ascend As Boolean
            Public sortMethod As Char

            Public Function Clone() As Object Implements System.ICloneable.Clone
                Dim right As factorDefine = New factorDefine()
                right.columnIndex = columnIndex
                right.ascend = ascend
                right.sortMethod = sortMethod

                Return right
            End Function
        End Class

        Private factors As vector(Of factorDefine) = Nothing

        Protected Function parseFactor(ByVal factor As String) As Boolean
            Dim extCode As Boolean = True
            Dim newfactor As factorDefine = New factorDefine()
            Dim index As Int64
            Dim len As Int64 = strlen(factor)
            If isemptystring(factor) Then
                extCode = False
            Else
                index = 0
                If factor(index) = character.plusSign Then
                    newfactor.ascend = True
                    index += 1
                ElseIf factor(index) = character.minusSign Then
                    newfactor.ascend = False
                    index += 1
                Else
                    newfactor.ascend = True
                End If

                If Not index >= len Then
                    Select Case Char.ToLower(factor(index))
                        Case sortMethodDefine.string
                            newfactor.sortMethod = sortMethodDefine.string
                            index += 1
                        Case sortMethodDefine.number
                            newfactor.sortMethod = sortMethodDefine.number
                            index += 1
                        Case sortMethodDefine.utf8
                            newfactor.sortMethod = sortMethodDefine.utf8
                            index += 1
                        Case Else
                            newfactor.sortMethod = sortMethodDefine.string
                    End Select
                    newfactor.columnIndex = Convert.ToInt64(strright(factor, len - index))
                Else
                    extCode = False
                End If

                factors.push_back(newfactor)
            End If

            Return extCode
        End Function

        Public Function initial(ByVal factors As vector(Of String)) As Boolean
            Dim i As Int64
            Dim extCode As Boolean = True
            If Me.factors Is Nothing Then
                Me.factors = New vector(Of factorDefine)
            Else
                Me.factors.clear()
            End If
            If Not factors Is Nothing Then
                For i = 0 To factors.size() - 1
                    If Not parseFactor(factors(i)) Then
                        extCode = False
                    End If
                Next
            End If

            Return extCode
        End Function

        Private Function comparelite(ByVal x As vector(Of String), ByVal y As vector(Of String) _
                                     , ByVal factor As factorDefine) As Int64
            Dim rtn As Int64
            If (x Is Nothing OrElse y Is Nothing OrElse factor Is Nothing) OrElse _
                (factor.columnIndex >= x.size() OrElse _
                factor.columnIndex >= y.size()) Then
                rtn = 0
            Else
                Select Case factor.sortMethod
                    Case sortMethodDefine.number
                        Dim xx As Double
                        Dim yy As Double
                        xx = Convert.ToDouble(x(factor.columnIndex))
                        yy = Convert.ToDouble(y(factor.columnIndex))
                        If xx > yy Then
                            rtn = 1
                        ElseIf xx < yy Then
                            rtn = -1
                        Else
                            rtn = 0
                        End If
                    Case sortMethodDefine.utf8
                        Dim xx As bytes = Nothing
                        Dim yy As bytes = Nothing
                        xx = New bytes(encoding.utf8.GetBytes(x(factor.columnIndex)))
                        yy = New bytes(encoding.utf8.GetBytes(y(factor.columnIndex)))
                        rtn = xx.CompareTo(yy)
                    Case Else
                        Dim xx As String
                        Dim yy As String
                        xx = x(factor.columnIndex)
                        yy = y(factor.columnIndex)
                        If xx > yy Then
                            rtn = 1
                        ElseIf xx < yy Then
                            rtn = -1
                        Else
                            rtn = 0
                        End If
                End Select

                If Not factor.ascend Then
                    rtn = -rtn
                End If
            End If

            Return rtn
        End Function

        Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
            On Error Resume Next
            Dim xx As vector(Of String) = Nothing
            Dim yy As vector(Of String) = Nothing
            Dim i As Int64
            Dim cmp As Int32
            xx = convertor.cast(Of vector(Of String))(x)
            yy = convertor.cast(Of vector(Of String))(y)

            If Not (xx Is Nothing Or yy Is Nothing Or factors Is Nothing) Then
                For i = 0 To factors.size() - 1
                    cmp = comparelite(xx, yy, factors(i))
                    If cmp <> 0 Then
                        Exit For
                    End If
                Next

                Return cmp
            End If
        End Function

        Public Sub New(Optional ByVal factors As vector(Of String) = Nothing)
            If Not factors Is Nothing Then
                initial(factors)
            End If
        End Sub
    End Class
End Namespace
